package org.ala.tiktools.rpc.kcp.protocol.tools;

import org.ala.tiktools.rpc.kcp.config.RpcKcpConfigInfo;
import org.ala.tiktools.rpc.kcp.protocol.IKcp;
import org.ala.tiktools.rpc.kcp.protocol.Kcp;

/**
 * @author ala
 * @date 2025-04-13 19:21
 */
public class KcpProbe {


    /**
     *  绑定的kcp
     */
    protected Kcp kcp;
    /**
     *  状态
     */
    protected int probe;


    /**
     * 是否询问窗口相关参数
     */
    protected int probeWait;
    /**
     *  上次询问对方窗口时间戳
     */
    protected int tsProbe;


    public KcpProbe(Kcp kcp) {
        this.kcp = kcp;
        this.probe = 0;
    }


    /**
     *  置位
     */
    public void probe(int probe) {
        this.probe |= probe;
    }


    /**
     *  是否发送询问窗口大小消息
     */
    public boolean isAskWnd() {
        return (probe & IKcp.IKCP_ASK_SEND) == 1;
    }
    /**
     *  是否发送回答窗口大小消息
     */
    public boolean isTellWnd() {
        return (probe & IKcp.IKCP_ASK_TELL) == 1;
    }
    /**
     *  清空probe
     */
    public void clear() {
        probe = 0;
    }


    /**
     *  判断是否需要发送窗口询问
     */
    public void probeAskTell() {
        if (kcp.getRmtWnd() == 0) {
            if (probeWait == 0) {
                probeWait = RpcKcpConfigInfo.INSTANCE.getiKcpProbeInit();
                tsProbe = kcp.getCurrent() + probeWait;
            } else {
                if (kcp.getCurrent() >= tsProbe) {
                    if (probeWait < RpcKcpConfigInfo.INSTANCE.getiKcpProbeInit()) {
                        probeWait = RpcKcpConfigInfo.INSTANCE.getiKcpProbeInit();
                    }
                    probeWait += probeWait / 2;
                    if (probeWait > RpcKcpConfigInfo.INSTANCE.getiKcpProbeLimit()) {
                        probeWait = RpcKcpConfigInfo.INSTANCE.getiKcpProbeLimit();
                    }
                    tsProbe = kcp.getCurrent() + probeWait;
                    probe |= IKcp.IKCP_ASK_SEND;
                }
            }
        } else {
            tsProbe = 0;
            probeWait = 0;
        }
    }

    public int getProbe() {
        return probe;
    }
}
